using System;
using System.Collections.Generic;
using System.DirectoryServices;

namespace Common.Security
{
    /// <summary>
    /// 
    /// </summary>
    public class LdapUtility
    {
        string _LdapConn = string.Empty;
        string _UserName = string.Empty;
        string _Password = string.Empty;

        /// <summary>
        /// 
        /// </summary>
        public LdapUtility()
        {
            this._LdapConn = string.Empty;
            this._UserName = string.Empty;
            this._Password = string.Empty;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public LdapUtility(string conn, string username, string password)
        {
            this._LdapConn = conn;
            this._UserName = username;
            this._Password = password;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="objType"></param>
        /// <returns></returns>
        public List<string> GetLdapObjectNames(LdapObjectType objType)
        {
            DirectorySearcher ds = new DirectorySearcher();
            ds.SearchRoot = new DirectoryEntry("");	// start searching from local domain
            if (this._LdapConn.Length > 0)
            {
                ds.SearchRoot = new DirectoryEntry(this._LdapConn, this._UserName, this._Password, AuthenticationTypes.Secure);
            }
            ds.Filter = GetFilterString(objType);		// get the LDAP filter string based on selections on the form
            ds.PropertyNamesOnly = true;		// this will get names of only those properties to which a value is set
            ds.PropertiesToLoad.Add("name");

            ds.ReferralChasing = ReferralChasingOption.None;

            
            ds.Sort = new SortOption("name", SortDirection.Ascending);

            List<string> ldapObjNameList = new List<string>();

            // start searching
            SearchResultCollection src = ds.FindAll();
            try
            {
                foreach (SearchResult sr in src)
                    this.AddObjectToList(ref ldapObjNameList, sr.GetDirectoryEntry());
            }
            catch (Exception e)
            {
                throw new Exception(e.ToString());
            }
            finally
            {
                src.Dispose();
                ds.Dispose();
            }

            return ldapObjNameList;
        }

        private void AddObjectToList(ref List<string> objNameList, DirectoryEntry de)
        {
            string objName = de.Name.Substring(3);
            objNameList.Add(objName);
        }

        private string GetFilterString(LdapObjectType ldapObjType)
        {
            // form the filter string for directory search
            string filter = "";
            
            if (ldapObjType== LdapObjectType.User)
                filter += FormFilter("user", "");
            if (ldapObjType== LdapObjectType.Computer)
                filter += FormFilter("computer", "");
            if (ldapObjType== LdapObjectType.Printer)
                filter += FormFilter("printQueue", "");
            if (ldapObjType == LdapObjectType.Group)
                filter += FormFilter("group", "");

            // add all the above filter strings
            return "(|" + filter + ")";
        }

        private string FormFilter(string objectCategory, string filter)
        {
            String result;
            result = String.Format("(&(objectCategory={0})(name={1}))", objectCategory, filter);
            return result;
        }
    }
}
